#define _USE_MATH_DEFINES

# include<iostream>
# include<cmath>
# include"EquationSolver.h"

using namespace::std;

/**
* @brief 用于把给定的角度转为对应弧度表示
* 
*/
double AnglePi(double x)
{
    return (x * M_PI / 180);
}

/**
* @brief 把给定方程问题移项做差转为函数求零点问题，构造相应函数
* 
*/
class Fun : public Function
{
private:
    double l, h, beta, A, B, C, D, E;
public:
    Fun(double _l, double _h, double _D, double _beta)
    {
        l = _l; h = _h; D = _D; beta = AnglePi(_beta);
        A = l * sin(beta);
        B = l * cos(beta);
        C = (h+0.5*D) * sin(beta) - 0.5 * D * tan(beta);
        E = (h+0.5*D) * cos(beta) - 0.5 * D;
    };

    double operator()(double a)
    {
        double x = AnglePi(a);
        return (A*sin(x)*cos(x) + B*sin(x)*sin(x) - C*cos(x) - E*sin(x));
    };
};

/**
* @brief 主函数
* 
*/
int main()
{
    cout << "Solution for Qustion F: " << endl;

    // Topic (a)
    cout << "Topic (a):" << endl;
    double x1, y1;
    Fun f1(89, 49, 55, 11.5);
    Newton NewSolve1(40, 0.001, 10, f1);
    x1 = NewSolve1.solve();
    y1 = f1(x1);
    cout << "By Newton's method, the angle alpha is " << x1 << ", and now the value of equation is " << y1 << endl;
    
    // Topic (b)
    cout << "Topic (b):" << endl;
    double x2, y2;
    Fun f2(89, 49, 30, 11.5);
    Newton NewSolve2(33.001, 0.001, 10, f2);
    x2 = NewSolve2.solve();
    y2 = f2(x2);
    cout << "By Newton's method, the angle alpha is " << x2 << ", and now the value of equation is " << y2 << endl;
    
    // Topic (c)
    cout << "Topic (c):" << endl;
    double x3, y3;
    Fun F(89, 49, 50, 11.5);
    Secant SecSolve1(85, 80, 0.0001, 0.0001, 10, F);
    x3 = SecSolve1.solve();
    y3 = F(x3);
    cout << "Selecit the initial value x0 = 85, x1 = 80. " << endl;
    cout <<  "By secant method, the angle alpha is " << x3 << ", and now the value of equation is " << y3 << endl;
    // 再选取一组初值来得到另一组结果
    double x4, y4;
    Secant SecSolve2(88, 86, 0.0001, 0.0001, 10, F);
    x4 = SecSolve2.solve();
    y4 = F(x4);
    cout << "Selecit the initial value x0 = 88, x1 = 86. " << endl;
    cout <<  "By secant method, the angle alpha is " << x4 << ", and now the value of equation is " << y4 << endl;
    
    cout << "" << endl;
    return 0;
}